/**
 * @author		Ben Layet
 * @version 	1.0
 * @date		25 Sep 2008
 */

package org.ignoramus.common.string;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Japanese string operations.
 */
public class JapaneseString
{
	/** Katakana */
	private static final String					katakana			= "アイウエオカキクケコガギグゲゴサシスセソザジズゼゾタチツテトダヂヅデドナニヌネノハヒフヘホバビブベボパピプペポマミムメモラリルレロヤユヨワヲンッャュョ";

	/** Hiragana */
	private static final String					hiragana			= "あいうえおかきくけこがぎぐげごさしすせそざじずぜぞたちつてとだぢづでどなにぬねのはひふへほばびぶべぼぱぴぷぺぽまみむめもらりるれろやゆよわをんっゃゅょ";

	/** Romaji */
	private static final String[]				romaji			= { "a", "i", "u", "e", "o", "ka", "ki", "ku", "ke", "ko", "ga", "gi", "gu", "ge",
			"go", "sa", "si", "su", "se", "so", "za", "zi", "zu", "ze", "zo", "ta", "ti", "tu", "te", "to", "da", "di", "du", "de", "do", "na", "ni",
			"nu", "ne", "no", "ha", "hi", "hu", "he", "ho", "ba", "bi", "bu", "be", "bo", "pa", "pi", "pu", "pe", "po", "ma", "mi", "mu", "me", "mo",
			"ra", "ri", "ru", "re", "ro", "ya", "yu", "yo", "wa", "wo", "n", "/", "xa", "xu", "xo", };

	/** The map of contractions */
	private static final Map<String, String>	contractions	= new HashMap<String, String>();
	/** The map of expansions */
	private static final Map<String, String>	expansions		= new HashMap<String, String>();
	/** All punctuation signs */
	private static final String					punctuation_signs	= " ~.?/<>;:!\"£$%^&*()_-\\|@#+=、＜。＞・　？’”￥｜！＠＃＄％＾＆＊（）＿＋＝－／．，「」〜～";

	static
	{
		//initialise the contractions map
		contractions.put("f", "h");
		// little ya yu and yo
		contractions.put("kixa", "kya");
		contractions.put("kixu", "kyu");
		contractions.put("kixo", "kyo");
		contractions.put("gixa", "gya");
		contractions.put("gixu", "gyu");
		contractions.put("gixo", "gyo");
		contractions.put("sixa", "sha");
		contractions.put("sixu", "shu");
		contractions.put("sixo", "sho");
		contractions.put("zixa", "ja");
		contractions.put("zixu", "ju");
		contractions.put("zixo", "jo");
		contractions.put("jixa", "ja");
		contractions.put("jixu", "ju");
		contractions.put("jixo", "jo");
		contractions.put("tixa", "cha");
		contractions.put("tixu", "chu");
		contractions.put("tixo", "cho");
		contractions.put("dixa", "dja");
		contractions.put("dixu", "dju");
		contractions.put("dixo", "djo");
		contractions.put("nixu", "nyu");
		contractions.put("nixo", "nyo");
		contractions.put("hixa", "hya");
		contractions.put("hixu", "hyu");
		contractions.put("hixo", "hyo");
		contractions.put("bixa", "bya");
		contractions.put("bixu", "byu");
		contractions.put("bixo", "byo");
		contractions.put("pixa", "pya");
		contractions.put("pixu", "pyu");
		contractions.put("pixo", "pyo");
		contractions.put("mixa", "mya");
		contractions.put("mixu", "myu");
		contractions.put("mixo", "myo");
		contractions.put("rixa", "rya");
		contractions.put("rixu", "ryu");
		contractions.put("rixo", "ryo");
		// Little tsu
		contractions.put("/k", "kk");
		contractions.put("/g", "gg");
		contractions.put("/s", "ss");
		contractions.put("/z", "zz");
		contractions.put("/t", "tt");
		contractions.put("/d", "dd");
		contractions.put("/n", "nn");
		contractions.put("/h", "hh");
		contractions.put("/b", "bb");
		contractions.put("/p", "pp");
		contractions.put("/m", "mm");
		contractions.put("/r", "rr");
		
		
		//initialise the expansions map
		expansions.put("ti", "chi");
		expansions.put("di", "dji");
		expansions.put("tu", "tsu");
		expansions.put("du", "dsu");
		expansions.put("np", "mp");
		expansions.put("nb", "mb");
		expansions.put("zi", "ji");
		expansions.put("si", "shi");
	}

	/**
	 * Convert a string to romaji.
	 * @param string hiragana, katakana or non official romaji
	 * @return the official romaji.
	 */
	public static String toRomaji(String string)
	{
		//set to lower case (just in case)
		string = string.toLowerCase();

		//loop through all the characters
		for (int i = 0; i < katakana.length(); i++)
		{
			string = string.replace(new Character(katakana.charAt(i)).toString(), romaji[i]);
			string = string.replace(new Character(hiragana.charAt(i)).toString(), romaji[i]);
		}
		
		//convert to official romaji and returns
		return toOfficialRomaji(string);
	}

	/**
	 * Convert a non official romaji string to offical romaji.
	 * @param string non official romaji
	 * @return the official romaji.
	 */
	public static String toOfficialRomaji(String romajiInput)
	{
		//loop through all the contractions
		for (Iterator<String> iterator = contractions.keySet().iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			String value = contractions.get(key);
			romajiInput = romajiInput.replace(key, value);
		}
		
		//loop through all the expansions
		for (Iterator<String> iterator = expansions.keySet().iterator(); iterator.hasNext();)
		{
			String key = iterator.next();
			String value = expansions.get(key);
			romajiInput = romajiInput.replace(key, value);
		}
		
		//return the result
		return romajiInput;
	}

	/**
	 * Remove all romaji and Japanese punctuation.
	 * @param input the original string.
	 * @return the same string without the punctuation.
	 */
	public static String removePunctuation(String input)
	{
		//loop through all the punctuation signs
		for (int i = 0; i < punctuation_signs.length(); i++)
		{
			input = input.replace(new Character(punctuation_signs.charAt(i)).toString(), "");
		}
		
		//return the result
		return input;
	}
}
